/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package modbus;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;
import java.util.Vector;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Leandro
 */
public class DriverSerie extends Driver implements SerialPortEventListener {

    private SerialPort serialPort;
    
    

     

    public boolean connectSerial(String portName, int speed, int dataBits, int stopBits, String paridad, int time, int reint) {
        this.timeout = time;
        this.nroReintentos = reint;
        return this.connectSerial(portName, speed, dataBits, stopBits, paridad);
    }

    public boolean connectSerial(String portName, int speed, int dataBits, int stopBits, String paridad) {
        CommPortIdentifier portIdentifier;
        boolean conn = false;
        int paridadAux = 0;
        int dataBitsAux = 0;
        int stopBitsAux = 0;
        if ("EVEN".equals(paridad)) {
            paridadAux = SerialPort.PARITY_EVEN;
        }
        if ("ODD".equals(paridad)) {
            paridadAux = SerialPort.PARITY_ODD;
        }
        if ("NONE".equals(paridad)) {
            paridadAux = SerialPort.PARITY_NONE;
        }
        if (dataBits == 5) {
            dataBitsAux = SerialPort.DATABITS_5;
        }
        if (dataBits == 6) {
            dataBitsAux = SerialPort.DATABITS_6;
        }
        if (dataBits == 7) {
            dataBitsAux = SerialPort.DATABITS_7;
        }
        if (dataBits == 8) {
            dataBitsAux = SerialPort.DATABITS_8;
        }
        if (stopBits == 1) {
            stopBitsAux = SerialPort.STOPBITS_1;
        }
        if (stopBits == 2) {
            stopBitsAux = SerialPort.STOPBITS_2;
        }

        try {
            portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            if (portIdentifier.isCurrentlyOwned()) {

                System.out.println("El puerto esta en uso");
                SuscriptorMensajes.getI().notificar("El puerto " + portName + " esta en uso");

            } else {
                serialPort = (SerialPort) portIdentifier.open("RTU",
                        2000);
                serialPort.setSerialPortParams(speed, dataBitsAux,
                        stopBitsAux, paridadAux);

//                                serialPort.enableReceiveTimeout(500);
                inputStream = serialPort.getInputStream();
                outputStream = serialPort.getOutputStream();


                connected = true;
                System.out.println(id + " connection on " + portName
                        + " established");
                conn = true;
            }
        } catch (NoSuchPortException e) {
            System.out.println(id + " the connection could not be made");

            e.printStackTrace();
        } catch (PortInUseException e) {
            System.out.println(id + "the connection could not be made");
            e.printStackTrace();
            SuscriptorMensajes.getI().notificar("Puerto en uso");
        } catch (UnsupportedCommOperationException e) {
            System.out.println(id + "the connection could not be made");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println(id + "the connection could not be made");
            e.printStackTrace();
        }
        try {
            serialPort.addEventListener(this);
        } catch (TooManyListenersException ex) {
            Logger.getLogger(DriverSerie.class.getName()).log(Level.SEVERE, null, ex);
        }
        return conn;
    }


    public boolean disconnect() {
        boolean disconn = true;
//		end = true;

        try {
            outputStream.close();
            inputStream.close();
            outputStream.flush();

        } catch (IOException e) {
            e.printStackTrace();
            disconn = false;
        }

        serialPort.close();
        connected = false;

        System.out.println("Desconectado");
        SuscriptorMensajes.getI().notificar("Desconectado");
        return disconn;
    }

    

    

   

    public SerialPort getSerialPort() {
        return serialPort;
    }

    public void setSerialPort(SerialPort serialPort) {
        this.serialPort = serialPort;
    }

    

    public byte[] receive() {
        int cantInt = 0;
        boolean recibi = false;
        byte[] buffer = new byte[1024];
        int len = -1, i, temp;
        InputStream in = this.getInputStream();
        byte[] aux = null;
        byte[] aux2;
        int[] crcCalc;
        if (isConnected()) {
            try {
//                    do{
                
                if ((in.available()) > 0) {
                    if ((len = in.read(buffer)) > -1) {
                        recibi = true;
                        aux = new byte[len];

                        for (i = 0; i < len; i++) {
                            //Código de tratamiento de la informacion
                            aux[i] = buffer[i];

                        }

                        aux2 = new byte[aux.length - 2];
                        for (int j = 0; j < aux2.length; j++) {
                            aux2[j] = aux[j];
                        }
                        crcCalc = CRC.calculateCRC(aux2, 0, aux2.length);
                        if ((byte) crcCalc[0] != aux[aux.length - 2] || (byte) crcCalc[1] != aux[aux.length - 1]) {
                            //Error de CRC
                            SuscriptorMensajes.getI().notificar("Error de CRC al recibir");
                        }


                    }
//                         }else{
//                            cantInt++;
//                            SuscriptorMensajes.getI().notificar("Reintento N°:"+(cantInt-1));
//                            try {
//                                SuscriptorMensajes.getI().notificar("Intentando dormir");
//                                this.wait(this.timeout);
//                                } catch (InterruptedException ex) {
//                                    Logger.getLogger(DriverSerie.class.getName()).log(Level.SEVERE, null, ex);
//                                    SuscriptorMensajes.getI().notificar("Excepcion tratando de dormir");
//                                }
//                        }
//                    }while(cantInt<this.nroReintentos && !recibi);

                }
            } catch (IOException ex) {
                Logger.getLogger(ExpertoComunicacion.class.getName()).log(Level.SEVERE, null, ex);
                System.out.println("no pude leer");
            }
        } else {
            SuscriptorMensajes.getI().notificar("Driver no conectado");
        }

        return aux;
    }

    public boolean send(String msj) {
        boolean success = false;
        if (isConnected()) {
            try {
                outputStream.write(msj.getBytes());
                success = true;
            } catch (IOException e) {
                disconnect();
            }
        } else {
            System.out.println("No hay un puerto conectado");
            SuscriptorMensajes.getI().notificar("Driver no conectado");
        }
        return success;
    }

    public boolean send(Paquete p) {
        boolean success = false;
        if (isConnected()) {
            try {
                outputStream.write(p.getPaqueteSerial());
                success = true;
            } catch (IOException e) {
                SuscriptorMensajes.getI().notificar("No se pudo enviars");
                disconnect();
            }
        } else {
            System.out.println("No hay un puerto conectado");
            SuscriptorMensajes.getI().notificar("No esta conectado el driver");
        }
        return success;
    }

    public static Vector<String> getPortNames() {
        Enumeration<CommPortIdentifier> portIdentifiers = CommPortIdentifier.getPortIdentifiers();
        Vector<String> rta = new Vector<String>();
        do {
            CommPortIdentifier puerto = portIdentifiers.nextElement();
            rta.add(puerto.getName());
        } while (portIdentifiers.hasMoreElements());
        return rta;
    }

    
    public void serialEvent(SerialPortEvent spe) {
        if(spe.getEventType()==SerialPortEvent.DATA_AVAILABLE){
            //Hay datos para leer
            this.expertoComunicaciones.notify();
        }
    }



    
}
